// Aaron Schraufnagel
// Joel Hunsaker
// TCSS 360 TeamDAMN
// For OnTrack System
// 11/25/14
package teamdamn.model;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Scanner;

/**
 * The ResponseList class creates a list of responses imported from text files
 * containing questions and answers.
 * @author Aaron Schraufnagel
 * @author Joel Hunsaker
 * @date Last Edited: 11/30/14
 */
public class ResponseList extends Observable {

	private ArrayList<Observer> observers;
    List<Response> myResponses;
    
    /**
     * Default constructor for ResponseList, creates a list of 
     * observers and of responses. 
     * @author joelhun
     */
    public ResponseList() {
    	observers = new ArrayList<Observer>();
    	myResponses = new LinkedList<Response>();
    }
    /**
     * Constructor taking a pre-generated list of responses.
     * @param r List of responses to be used by this constructor.
     * @author joelhun
     */
    public ResponseList(List<Response> r) {
    	myResponses = r;
    	observers = new ArrayList<Observer>();
    }
    /**
     * Constructor taking a filepath pointing to the file with
     * which to populate the answer list.
     * @param filepath Path to the file containing an answer list.
     * @author joelhun
     */
    public ResponseList(String filepath) {
        //create a response list from a file
    	myResponses = new LinkedList<Response>();
        populateFromFile(filepath);
    }
    /**
     * Adds an Observer to the list of observers to be notified by this response list.
     * @param o The Observer to be added.
     * @author joelhun
     */
    public void registerObserver(Observer o) {
    	observers.add(o);
    }
    /**
     * Loops through the kept list of Observers and notifies each that a change
     * has occurred.
     * @author joelhun
     */
    public void notifyObservers() {
    	for (int i = 0; i < observers.size(); i++) {
    		Observer observer = (Observer) observers.get(i);
    		observer.update(this, myResponses);
    	}
    }
    

    /**
     * Updates the answer list based on the file pointed to
     * by the param filepath
     * @param filepath Path to the file containing the updated
     * list of answer.
     * @author joelhun
     */
    public void updateResponses(String filepath) {
    	populateFromFile(filepath);
    }
    
    /**
     * Populates the answer list by parsing the passed file.
     * @param filepath Path to the file containing the answer list.
     * @author joelhun
     * @author jrsto674
     */
    private void populateFromFile(String filepath) {
        File f = new File(filepath);
        List<Response> updatedResponses = new LinkedList<Response>();
        try {
        	Scanner scan = new Scanner(f);
            Response r = new Response(scan.nextLine()); //automatically grabs the first question. All input files MUST contain at least one question.
            while (scan.hasNextLine()) {
                String lineText = scan.nextLine();
                Scanner lineScanner = new Scanner(lineText);
                if (lineScanner.hasNext()) {
	                String questionOrAnswer = lineScanner.next(); //grabs the first token. Answers: "Y" editable, "N" not editable, anything else is a question
	                if (questionOrAnswer.equals("Y") || questionOrAnswer.equals("N")) {
	                	String answer = lineText.substring(2, lineText.length()); // slices the "Y " out of the string.
	                	r.addAnswer(answer, questionOrAnswer.equals("Y"));
	                } else { // we found a new question
	                	updatedResponses.add(r); //ad the finalized response to the list of responses
	                	r = new Response(lineText); //create a new Response.
	                }
                }
                lineScanner.close();
            } 
            updatedResponses.add(r);
            myResponses = updatedResponses;
            listUpdated();
            scan.close();
        }
        catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            
        }
    }
    
    /**
     * @author joelhun
     */
    private void listUpdated() {
    	setChanged();
    	notifyObservers();
    }
    
    /**
     * @author joelhun
     * @return The list of responses
     */
    public List<Response> getAllResponses() {
        return myResponses;
    }
    
    /**
     * When an analyst searches for a keyword in the ResponseList, the list
     * is compared to the keyword term.
     * @author Aaron Schraufnagel
     * @date Last Edited: 11/30/14
     * @param keyword The search keyword
     * @return the search results
     */
    public String getKeywordSearchResults(String keyword) {
    	if (keyword.equals("")) {
    		return keyword;
    	}
    	StringBuilder sb = new StringBuilder(100);
    	for (Response r : myResponses) {
    		String question = r.getQuestion().toLowerCase();
    		boolean newQuestion = true;
    		List<ResponseAnswer> answers= r.getAnswers();
    		if (question.contains(keyword.toLowerCase())) {
    			sb.append("QUESTION: ");
        		sb.append(r.getQuestion());
        		sb.append(System.getProperty("line.separator"));
        		for (ResponseAnswer ra : answers ) {
        			sb.append("     ");
        			if (!ra.isEditable()) {
        				sb.append("NOT "); 				
        			}
        			sb.append("EDITABLE: ");
        			sb.append(ra.toString());

        			sb.append(System.getProperty("line.separator"));
        		}
        		sb.append(System.getProperty("line.separator"));
    		} else {
    			for (ResponseAnswer ra : answers ) {
    				if (ra.toString().toLowerCase().contains(keyword.toLowerCase())) {
    					if (newQuestion) { 
    						sb.append("QUESTION: ");
        	        		sb.append(r.getQuestion());
        	        		sb.append(System.getProperty("line.separator"));
    					}
    	        		sb.append("     ");
	        			if (!ra.isEditable()) {
	        				sb.append("NOT "); 				
	        			}
	        			sb.append("EDITABLE: ");
	        			sb.append(ra.toString());

	        			sb.append(System.getProperty("line.separator"));
	        			newQuestion = false;
	        		}
    			}
    		}
    	}
    	return sb.toString();
    }
    
    /**
     * When an analyst searches for a question in the ResponseList, the list
     * is compared to the question term.
     * @author Aaron Schraufnagel
     * @date Last Edited: 11/30/14
     * @param aQuestion The search question
     * @return the search results
     */
    public String getQuestionSearchResults(String aQuestion) {
    	if (aQuestion.equals("")) {
    		return aQuestion;
    	}
    	StringBuilder sb = new StringBuilder(100);
    	for (Response r : myResponses) {
    		String question = r.getQuestion().toLowerCase();
    		List<ResponseAnswer> answers= r.getAnswers();
    		if (question.equals(aQuestion.toLowerCase())) {
    			sb.append("QUESTION: ");
        		sb.append(r.getQuestion());
        		sb.append(System.getProperty("line.separator"));
        		for (ResponseAnswer ra : answers ) {
        			sb.append("     ");
        			if (!ra.isEditable()) {
        				sb.append("NOT "); 				
        			}
        			sb.append("EDITABLE: ");
        			sb.append(ra.toString());

        			sb.append(System.getProperty("line.separator"));
        		}
        		sb.append(System.getProperty("line.separator"));
    		}
    	}
    	return sb.toString();
    }
    
    /**
     * @author joelhun
     */
    @Override
    public String toString() {
    	StringBuilder sb = new StringBuilder(100);
    	for (Response r : myResponses) {
    		sb.append("QUESTION: ");
    		sb.append(r.getQuestion());
    		sb.append(System.getProperty("line.separator"));
    		List<ResponseAnswer> answers= r.getAnswers();
    		for (ResponseAnswer ra : answers ) {
    			sb.append("     ");
    			if (!ra.isEditable()) {
    				sb.append("NOT "); 				
    			}
    			sb.append("EDITABLE: ");
    			sb.append(ra.toString());

    			sb.append(System.getProperty("line.separator"));
    		}
    		sb.append(System.getProperty("line.separator"));
    	}
    	return sb.toString();
    }
    
}
